using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
#if TEST
using Xunit;
#endif

namespace Fadd.Parser.Evaluator
{
    /// <summary>
    /// Used to parse SQL conditions
    /// </summary>
    public class Parser
    {
        private Tokenizer _tokenizer;

        /// <summary>
        /// New Line, Line Feed, Tab and Space.
        /// </summary>
        public const string WhiteSpaces = "\r\n\t ";

        /// <summary>
        /// Initializes a new instance of the <see cref="Parser"/> class.
        /// </summary>
        public Parser()
        {
            Setup();
        }

        /// <summary>
        /// Setup all tokens
        /// </summary>
        private void Setup()
        {
            _tokenizer = new Tokenizer();

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (type.Namespace == GetType().Namespace + ".ParseTreeTokens")
                    _tokenizer.Prototypes.Add((ParseTreeToken)Activator.CreateInstance(type, null));
            }
        }


        /// <summary>
        /// Parse the tree
        /// </summary>
        /// <param name="text">Text to parse.</param>
        /// <returns>a parsed tree</returns>
        public ParseTree Parse(string text)
        {
            ParseTree tree = new ParseTree();
            _tokenizer.Parse(text, tree);
            return tree;
        }


#if TEST
        [Fact]
        private void TestSimple()
        {
            ParseTree tree = Parse("  (UserName =   ? OR LastName =   ?) AND FirstName   != ?  ");
            PrintTree(tree);
        }

        [Fact]
        private void TestNotEqual()
        {
            ParseTree tree = Parse("FirstName != ?");
            PrintTree(tree);
        }
#endif

        private static void PrintTree(IEnumerable<Token> tree)
        {
            foreach (Token token in tree)
                PrintTree(token, 0);
        }

        private static void PrintTree(Token token, int spaces)
        {
            Debug.Write(string.Empty.PadLeft(spaces));
            Debug.WriteLine(token.ToString());
            foreach (Token child in token.Children)
                PrintTree(child, spaces + 2);
        }
    }
}
